﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using QuickGraph;


namespace snat.model {
    public class Edge : IComparable<Edge>, IEdge<object> {

        /// <summary>
        /// Source node of the edge
        /// </summary>
        public BaseNode Source { get; private set; }
        /// <summary>
        /// Target node of the edge
        /// </summary>
        public BaseNode Target { get; private set; }

        /// <summary>
        /// MessageIDs is a list of ID numbers of the messages sent along this edge.
        /// </summary>
        public List<int> MessageIDs { get; private set; }

        /// <summary>
        /// This method is used to update the edge, adding a new message id to the MessageIDs property
        /// </summary>
        /// <param name="message">The message sent along this edge</param>
        private void MessageSentAlong(Message message, BaseNode source) {
            MessageIDs.Add(message.ID);
        }

        /// <summary>
        /// The weight of the edge. Defaults to 1.0.
        /// </summary>
        public double Weight { get; set; }

        /// <summary>
        /// TimeStamp is the time at which the edge first came into being.
        /// </summary>
        public DateTime Timestamp { get; private set; }

        public Edge(BaseNode from, BaseNode to, DateTime _timeStamp, double _weight = 1) {
                this.Source = from;
                this.Target = to;
                MessageIDs = new List<int>();
                this.Weight = _weight;
                this.Timestamp = _timeStamp;
                Source.MessageSend += MessageSentAlong;
        }


        public override int GetHashCode() {
            long res = 2048 * Target.GetHashCode() + Source.GetHashCode();
            return (res.GetHashCode());
        }

        public override bool Equals(object obj) {
            Edge other = (Edge)obj;
            if (other == null) return false;
            return (other.Target.Equals(this.Target) && other.Source.Equals(this.Source));
        }

        /// <summary>
        /// This property is used for graph# integration. Returns the source of the edge.
        /// </summary>
        object IEdge<object>.Source {
            get { return NetworkModel.Instance.Nodes[Source.ID]; }
        }

        /// <summary>
        /// This property is used for graph# integration. Returns the target of the edge.
        /// </summary>
        object IEdge<object>.Target {
            get { return NetworkModel.Instance.Nodes[Target.ID]; }
        }

        /// <summary>
        /// Implementation of CompareTo method
        /// </summary>
        /// <param name="other">Edge to compare this edge with</param>
        /// <returns>0 if other has same source and target of this edge, 
        /// otherwise the CompareTo of this Weight and other's Weight</returns>
        public int CompareTo(Edge other) {
            if (other.Source.CompareTo(Source) == 0 &&
                other.Target.CompareTo(Target) == 0) return 0;
            return other.Weight.CompareTo(Weight);
        }

    }
}
